<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.4.1 / SVN信息: $Id: class.JCAT_DownloadFile.php 1510 2009-03-23 06:51:00Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/

/**
 * What's this Class ?
 *
 * @author		alee
 * @access		public
 */
class JCAT_DownloadFile implements JCAT_ISSMI
{

	/**
	 * 查询一个静态方法 是否在 HTTP 上公开
	 * 
	 * @access	public
	 * @param	$sMethodName	string	What's this Parameter ?
	 * @return	void
	 */
	static public function IsPublicOnHTTP( $sMethodName )
	{
		return in_array( strtolower($sMethodName), array('download') ) ;
	}

	
	

	/**
	 * 回应 HTTP 客户端的下载请求
	 * 此函数实现了 对 缓存  和  断点的支持
	 * 
	 * @access	public
	 * @param	$sFilePath						string		文件在服务器上的存储路径
	 * @param	$bRefresh=false					bool		强制更新，忽视客户端提供的缓存时间
	 * @param	$bNoHTTPLocation=false		bool		不进行 HTTP 重定向
	 * @return	void
	 */
	static public function Download($sFilePath,$bRefresh=false,$bNoHTTPLocation=false)
	{		
		// 检查文件是否存在
		if( !is_file($sFilePath) )
		{
			self::SendHTTPStatus(404,'File Not Found') ;
		}
		
		// 直接 重定向 到该文件的 HTTP地址
		if( !$bNoHTTPLocation and $sHTTPPath=self::GetDirectHTTPAccessPath($sFilePath,null,false) )
		{
			header("Location: {$sHTTPPath}") ;
			return ;
		}

		// 文件无法访问
		if( !is_readable($sFilePath) )
		{
			self::SendHTTPStatus(403,'File Forbidden') ;
		}
		
		// 文件修改时间
		$nMTime = $bRefresh? (time()+36000): filemtime($sFilePath) ;
		
		// 检查客户端缓存是否可用
		if( self::VerifyClientCache($nMTime) )
		{
			return ;
		}
		

		// 文件类型
		$theFile = new JCAT_File($sFilePath) ;
		$sExtName = $theFile->GetExtName(2) ;
		$sMimeType = self::GetMIMEType($sExtName) ;
		header("Content-Type: {$sMimeType}") ;
				

		// 文件下载起点; 断点续传支持
		$arrRet = array() ;
		if( !empty($_SERVER['HTTP_RANGE']) and preg_match('/^bytes=(\d+)\-/i',$_SERVER['HTTP_RANGE'],$arrRet) )
		{
			$nStart = $arrRet[1] ;
		}
		else
		{
			$nStart = 0 ;
		}
	
		// gzip 压缩
		if( function_exists('gzcompress') and !empty($_SERVER['HTTP_ACCEPT_ENCODING'])
			and strstr($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip')!==false )
		{
			ob_start("ob_gzhandler") ;
		}
		
		// 向客户端 传输文件
		$theFile->Open('r') ;
		$theFile->PrintContent(self::$nReadBufSize,$nStart) ;
		$theFile->Close() ;

	}
	
	/**
	 * HTTP 客户端 Cache 协商
	 * 返回一个bool 值：
	 *   false 代表客户端无缓存，或缓存不可用
	 *   true  代表客户端缓存可用，不必重新下载
	 *
	 * @access	public
	 * @param	$nResourceTime					int		请求资源的最后修改时间
	 * @param	$bSaveCacheOnClient=true		bool	是否在客户端保存缓存
	 * @return	bool
	 * @static
	 */
	static public function VerifyClientCache( $nResourceTime, $bSaveCacheOnClient=true )
	{
		if($bSaveCacheOnClient)
		{
			// 可以被客户端缓存
			header('Cache-Control: Public');
			
			// 修改时间
			header('Last-Modified: '.gmdate("D, d M Y H:i:s",$nResourceTime).' GMT');
		}
		
		// 项目状态： 不使用缓存
		if( JCAT_ProjectState::Get(JCAT_ProjectState::NO_CACHE) )
		{
			return false ;
		}
	
		// 缓存 仅在 apache 中支持以下功能
		if( function_exists('apache_request_headers'))
		{
			$arrheaders = apache_request_headers() ;
			
			if(isset($arrheaders['If-Modified-Since']))
			{
				// 返回 304
				$nClientCacheTime = strtotime($arrheaders['If-Modified-Since']) ;
				if($nResourceTime<=$nClientCacheTime)
				{
					$_COOKIE = array() ;
					header('Expires: '.gmdate("D, d M Y H:i:s",time()+3600).' GMT') ;
					self::SendHTTPStatus(304,'Not Modified') ;

					return true ;
				}
			}
		}
		
		return false ;
	}
	
	/**
	 * 发送 HTTP 状态 Header
	 *
	 * @access	public
	 * @param	$nCode		int
	 * @param	$sMsg		string
	 * @return	void
	 * @static 
	 */
	static public function SendHTTPStatus($nCode,$sMsg)
	{
		if (substr(php_sapi_name(), 0, 3) == 'cgi')
		{
			header("Status: {$nCode} {$sMsg}", true, $nCode);
		}
		else
		{
			header("{$_SERVER['SERVER_PROTOCOL']} {$nCode} {$sMsg}",true,$nCode);
		}		
	}
	
	/**
	 * 返回一个文件在 HTTP上 可访问的路径
	 * 
	 * @access	public
	 * @param	$sFilePath				string	文件存储路径
	 * @param	$sEntrance=null			string	访问入口
	 * @param	$bCanBeIndirect=true	string	在无法直接访问的时候，通过 self::Download() 方法 间接访问
	 * @return	void
	 */
	static public function GetHTTPAccessPath( $sFilePath, $sEntrance=null, $bCanBeIndirect=true )
	{
		if($sEntrance===null)
		{
			$sEntrance = JCAT_HTTPEntrance::GetCurrentEntrance() ;
		}
		
		$sRootPath = JCAT_HTTPEntrance::GetEntrancePath($sEntrance) ;
		
		// 文件名 是否区分 大小写
		$sFlag = JCAT_FSO::IsFileSystemCaseSensitive()? 'i': '' ;
		
		// 比较正则式
		$sRegExp = "|^{$sRootPath}(.*)$|{$sFlag}" ;
		
		// 在 HTTP可访问的路径中
		$arrRes = array() ;
		if( preg_match($sRegExp,$sFilePath,$arrRes) )
		{
			return "http://{$sEntrance}/$arrRes[1]" ;
		}

		// 不在 HTTP 路径中
		else
		{
			// 通过 SSMI 间接访问
			if($bCanBeIndirect)
			{
				$sResource = urlencode($sFilePath) ;
				return "http://{$sEntrance}/?controller=JCAT_SSMI&Class=".__CLASS__."&Method=Download&Param%5B%5D={$sResource}" ;
			}
			
			// 无法确定 url
			else
			{
				return null ;
			}
		}
	}	
	
	static public function EncodePath( $sPath )
	{
		$sPath = JCAT_Global::TidyPath($sPath) ;	
		return JCAT_Encode::Encode($sPath) ;
	}	
	
	
	static public function DecodePath( $sResource )
	{
		return JCAT_Encode::Decode($sResource) ;
	}
	
	/**
	 * 根据文件扩展名取得文件的 MIME 类型
	 *
	 * @access	public
	 * @param	$sExtName		string
	 * @return	string
	 */
	public function GetMIMEType($sExtName)
	{
		$sLowerExtName = strtolower($sExtName) ;
		return isset(self::$arrContentTypeTable[$sLowerExtName])?
				self::$arrContentTypeTable[$sLowerExtName]: 'text/unknow' ;
		
	}
	
	static public $nReadBufSize = 1024 ;
	
	static private $arrContentTypeTable = array(
		'*'=>'application/octet-stream'
		, '001'=>'application/x-001'
		, '301'=>'application/x-301'
		, '323'=>'text/h323'
		, '906'=>'application/x-906'
		, '907'=>'drawing/907'
		, 'a11'=>'application/x-a11'
		, 'acp'=>'audio/x-mei-aac'
		, 'ai'=>'application/postscript'
		, 'aif'=>'audio/aiff'
		, 'aifc'=>'audio/aiff'
		, 'aiff'=>'audio/aiff'
		, 'anv'=>'application/x-anv'
		, 'asa'=>'text/asa'
		, 'asf'=>'video/x-ms-asf'
		, 'asp'=>'text/asp'
		, 'asx'=>'video/x-ms-asf'
		, 'au'=>'audio/basic'
		, 'avi'=>'video/avi'
		, 'awf'=>'application/vnd.adobe.workflow'
		, 'biz'=>'text/xml'
		, 'bmp'=>'application/x-bmp'
		, 'bot'=>'application/x-bot'
		, 'c4t'=>'application/x-c4t'
		, 'c90'=>'application/x-c90'
		, 'cal'=>'application/x-cals'
		, 'cat'=>'application/vnd.ms-pki.seccat'
		, 'cdf'=>'application/x-netcdf'
		, 'cdr'=>'application/x-cdr'
		, 'cel'=>'application/x-cel'
		, 'cer'=>'application/x-x509-ca-cert'
		, 'cg4'=>'application/x-g4'
		, 'cgm'=>'application/x-cgm'
		, 'cit'=>'application/x-cit'
		, 'class'=>'java/*'
		, 'cml'=>'text/xml'
		, 'cmp'=>'application/x-cmp'
		, 'cmx'=>'application/x-cmx'
		, 'cot'=>'application/x-cot'
		, 'crl'=>'application/pkix-crl'
		, 'crt'=>'application/x-x509-ca-cert'
		, 'csi'=>'application/x-csi'
		, 'css'=>'text/css'
		, 'cut'=>'application/x-cut'
		, 'dbf'=>'application/x-dbf'
		, 'dbm'=>'application/x-dbm'
		, 'dbx'=>'application/x-dbx'
		, 'dcd'=>'text/xml'
		, 'dcx'=>'application/x-dcx'
		, 'der'=>'application/x-x509-ca-cert'
		, 'dgn'=>'application/x-dgn'
		, 'dib'=>'application/x-dib'
		, 'dll'=>'application/x-msdownload'
		, 'doc'=>'application/msword'
		, 'dot'=>'application/msword'
		, 'drw'=>'application/x-drw'
		, 'dtd'=>'text/xml'
		, 'dwf'=>'Model/vnd.dwf'
		, 'dwf'=>'application/x-dwf'
		, 'dwg'=>'application/x-dwg'
		, 'dxb'=>'application/x-dxb'
		, 'dxf'=>'application/x-dxf'
		, 'edn'=>'application/vnd.adobe.edn'
		, 'emf'=>'application/x-emf'
		, 'eml'=>'message/rfc822'
		, 'ent'=>'text/xml'
		, 'epi'=>'application/x-epi'
		, 'eps'=>'application/x-ps'
		, 'eps'=>'application/postscript'
		, 'etd'=>'application/x-ebx'
		, 'exe'=>'application/x-msdownload'
		, 'fax'=>'image/fax'
		, 'fdf'=>'application/vnd.fdf'
		, 'fif'=>'application/fractals'
		, 'fo'=>'text/xml'
		, 'frm'=>'application/x-frm'
		, 'g4'=>'application/x-g4'
		, 'gbr'=>'application/x-gbr'
		, 'gcd'=>'application/x-gcd'
		, 'gif'=>'image/gif'
		, 'gl2'=>'application/x-gl2'
		, 'gp4'=>'application/x-gp4'
		, 'hgl'=>'application/x-hgl'
		, 'hmr'=>'application/x-hmr'
		, 'hpg'=>'application/x-hpgl'
		, 'hpl'=>'application/x-hpl'
		, 'hqx'=>'application/mac-binhex40'
		, 'hrf'=>'application/x-hrf'
		, 'hta'=>'application/hta'
		, 'htc'=>'text/x-component'
		, 'htm'=>'text/html'
		, 'html'=>'text/html'
		, 'htt'=>'text/webviewhtml'
		, 'htx'=>'text/html'
		, 'icb'=>'application/x-icb'
		, 'ico'=>'image/x-icon'
		, 'ico'=>'application/x-ico'
		, 'iff'=>'application/x-iff'
		, 'ig4'=>'application/x-g4'
		, 'igs'=>'application/x-igs'
		, 'iii'=>'application/x-iphone'
		, 'img'=>'application/x-img'
		, 'ins'=>'application/x-internet-signup'
		, 'isp'=>'application/x-internet-signup'
		, 'IVF'=>'video/x-ivf'
		, 'java'=>'java/*'
		, 'jfif'=>'image/jpeg'
		, 'jpe'=>'image/jpeg'
		, 'jpe'=>'application/x-jpe'
		, 'jpeg'=>'image/jpeg'
		, 'jpg'=>'image/jpeg'
		, 'jpg'=>'application/x-jpg'
		, 'js'=>'application/x-javascript'
		, 'jsp'=>'text/html'
		, 'la1'=>'audio/x-liquid-file'
		, 'lar'=>'application/x-laplayer-reg'
		, 'latex'=>'application/x-latex'
		, 'lavs'=>'audio/x-liquid-secure'
		, 'lbm'=>'application/x-lbm'
		, 'lmsff'=>'audio/x-la-lms'
		, 'ls'=>'application/x-javascript'
		, 'ltr'=>'application/x-ltr'
		, 'm1v'=>'video/x-mpeg'
		, 'm2v'=>'video/x-mpeg'
		, 'm3u'=>'audio/mpegurl'
		, 'm4e'=>'video/mpeg4'
		, 'mac'=>'application/x-mac'
		, 'man'=>'application/x-troff-man'
		, 'math'=>'text/xml'
		, 'mdb'=>'application/msaccess'
		, 'mdb'=>'application/x-mdb'
		, 'mfp'=>'application/x-shockwave-flash'
		, 'mht'=>'message/rfc822'
		, 'mhtml'=>'message/rfc822'
		, 'mi'=>'application/x-mi'
		, 'mid'=>'audio/mid'
		, 'midi'=>'audio/mid'
		, 'mil'=>'application/x-mil'
		, 'mml'=>'text/xml'
		, 'mnd'=>'audio/x-musicnet-download'
		, 'mns'=>'audio/x-musicnet-stream'
		, 'mocha'=>'application/x-javascript'
		, 'movie'=>'video/x-sgi-movie'
		, 'mp1'=>'audio/mp1'
		, 'mp2'=>'audio/mp2'
		, 'mp2v'=>'video/mpeg'
		, 'mp3'=>'audio/mp3'
		, 'mp4'=>'video/mpeg4'
		, 'mpa'=>'video/x-mpg'
		, 'mpd'=>'application/vnd.ms-project'
		, 'mpe'=>'video/x-mpeg'
		, 'mpeg'=>'video/mpg'
		, 'mpg'=>'video/mpg'
		, 'mpga'=>'audio/rn-mpeg'
		, 'mpp'=>'application/vnd.ms-project'
		, 'mps'=>'video/x-mpeg'
		, 'mpt'=>'application/vnd.ms-project'
		, 'mpv'=>'video/mpg'
		, 'mpv2'=>'video/mpeg'
		, 'mpw'=>'application/vnd.ms-project'
		, 'mpx'=>'application/vnd.ms-project'
		, 'mtx'=>'text/xml'
		, 'mxp'=>'application/x-mmxp'
		, 'net'=>'image/pnetvue'
		, 'nrf'=>'application/x-nrf'
		, 'nws'=>'message/rfc822'
		, 'odc'=>'text/x-ms-odc'
		, 'out'=>'application/x-out'
		, 'p10'=>'application/pkcs10'
		, 'p12'=>'application/x-pkcs12'
		, 'p7b'=>'application/x-pkcs7-certificates'
		, 'p7c'=>'application/pkcs7-mime'
		, 'p7m'=>'application/pkcs7-mime'
		, 'p7r'=>'application/x-pkcs7-certreqresp'
		, 'p7s'=>'application/pkcs7-signature'
		, 'pc5'=>'application/x-pc5'
		, 'pci'=>'application/x-pci'
		, 'pcl'=>'application/x-pcl'
		, 'pcx'=>'application/x-pcx'
		, 'pdf'=>'application/pdf'
		, 'pdf'=>'application/pdf'
		, 'pdx'=>'application/vnd.adobe.pdx'
		, 'pfx'=>'application/x-pkcs12'
		, 'pgl'=>'application/x-pgl'
		, 'pic'=>'application/x-pic'
		, 'pko'=>'application/vnd.ms-pki.pko'
		, 'pl'=>'application/x-perl'
		, 'plg'=>'text/html'
		, 'pls'=>'audio/scpls'
		, 'plt'=>'application/x-plt'
		, 'png'=>'image/png'
		, 'png'=>'application/x-png'
		, 'pot'=>'application/vnd.ms-powerpoint'
		, 'ppa'=>'application/vnd.ms-powerpoint'
		, 'ppm'=>'application/x-ppm'
		, 'pps'=>'application/vnd.ms-powerpoint'
		, 'ppt'=>'application/vnd.ms-powerpoint'
		, 'ppt'=>'application/x-ppt'
		, 'pr'=>'application/x-pr'
		, 'prf'=>'application/pics-rules'
		, 'prn'=>'application/x-prn'
		, 'prt'=>'application/x-prt'
		, 'ps'=>'application/x-ps'
		, 'ps'=>'application/postscript'
		, 'ptn'=>'application/x-ptn'
		, 'pwz'=>'application/vnd.ms-powerpoint'
		, 'r3t'=>'text/vnd.rn-realtext3d'
		, 'ra'=>'audio/vnd.rn-realaudio'
		, 'ram'=>'audio/x-pn-realaudio'
		, 'ras'=>'application/x-ras'
		, 'rat'=>'application/rat-file'
		, 'rdf'=>'text/xml'
		, 'rec'=>'application/vnd.rn-recording'
		, 'red'=>'application/x-red'
		, 'rgb'=>'application/x-rgb'
		, 'rjs'=>'application/vnd.rn-realsystem-rjs'
		, 'rjt'=>'application/vnd.rn-realsystem-rjt'
		, 'rlc'=>'application/x-rlc'
		, 'rle'=>'application/x-rle'
		, 'rm'=>'application/vnd.rn-realmedia'
		, 'rmf'=>'application/vnd.adobe.rmf'
		, 'rmi'=>'audio/mid'
		, 'rmj'=>'application/vnd.rn-realsystem-rmj'
		, 'rmm'=>'audio/x-pn-realaudio'
		, 'rmp'=>'application/vnd.rn-rn_music_package'
		, 'rms'=>'application/vnd.rn-realmedia-secure'
		, 'rmvb'=>'application/vnd.rn-realmedia-vbr'
		, 'rmx'=>'application/vnd.rn-realsystem-rmx'
		, 'rnx'=>'application/vnd.rn-realplayer'
		, 'rp'=>'image/vnd.rn-realpix'
		, 'rpm'=>'audio/x-pn-realaudio-plugin'
		, 'rsml'=>'application/vnd.rn-rsml'
		, 'rt'=>'text/vnd.rn-realtext'
		, 'rtf'=>'application/msword'
		, 'rtf'=>'application/x-rtf'
		, 'rv'=>'video/vnd.rn-realvideo'
		, 'sam'=>'application/x-sam'
		, 'sat'=>'application/x-sat'
		, 'sdp'=>'application/sdp'
		, 'sdw'=>'application/x-sdw'
		, 'sit'=>'application/x-stuffit'
		, 'slb'=>'application/x-slb'
		, 'sld'=>'application/x-sld'
		, 'slk'=>'drawing/x-slk'
		, 'smi'=>'application/smil'
		, 'smil'=>'application/smil'
		, 'smk'=>'application/x-smk'
		, 'snd'=>'audio/basic'
		, 'sol'=>'text/plain'
		, 'sor'=>'text/plain'
		, 'spc'=>'application/x-pkcs7-certificates'
		, 'spl'=>'application/futuresplash'
		, 'spp'=>'text/xml'
		, 'ssm'=>'application/streamingmedia'
		, 'sst'=>'application/vnd.ms-pki.certstore'
		, 'stl'=>'application/vnd.ms-pki.stl'
		, 'stm'=>'text/html'
		, 'sty'=>'application/x-sty'
		, 'svg'=>'text/xml'
		, 'swf'=>'application/x-shockwave-flash'
		, 'tdf'=>'application/x-tdf'
		, 'tg4'=>'application/x-tg4'
		, 'tga'=>'application/x-tga'
		, 'tif'=>'image/tiff'
		, 'tif'=>'application/x-tif'
		, 'tiff'=>'image/tiff'
		, 'tld'=>'text/xml'
		, 'top'=>'drawing/x-top'
		, 'torrent'=>'application/x-bittorrent'
		, 'tsd'=>'text/xml'
		, 'txt'=>'text/plain'
		, 'uin'=>'application/x-icq'
		, 'uls'=>'text/iuls'
		, 'vcf'=>'text/x-vcard'
		, 'vda'=>'application/x-vda'
		, 'vdx'=>'application/vnd.visio'
		, 'vml'=>'text/xml'
		, 'vpg'=>'application/x-vpeg005'
		, 'vsd'=>'application/vnd.visio'
		, 'vsd'=>'application/x-vsd'
		, 'vss'=>'application/vnd.visio'
		, 'vst'=>'application/vnd.visio'
		, 'vst'=>'application/x-vst'
		, 'vsw'=>'application/vnd.visio'
		, 'vsx'=>'application/vnd.visio'
		, 'vtx'=>'application/vnd.visio'
		, 'vxml'=>'text/xml'
		, 'wav'=>'audio/wav'
		, 'wax'=>'audio/x-ms-wax'
		, 'wb1'=>'application/x-wb1'
		, 'wb2'=>'application/x-wb2'
		, 'wb3'=>'application/x-wb3'
		, 'wbmp'=>'image/vnd.wap.wbmp'
		, 'wiz'=>'application/msword'
		, 'wk3'=>'application/x-wk3'
		, 'wk4'=>'application/x-wk4'
		, 'wkq'=>'application/x-wkq'
		, 'wks'=>'application/x-wks'
		, 'wm'=>'video/x-ms-wm'
		, 'wma'=>'audio/x-ms-wma'
		, 'wmd'=>'application/x-ms-wmd'
		, 'wmf'=>'application/x-wmf'
		, 'wml'=>'text/vnd.wap.wml'
		, 'wmv'=>'video/x-ms-wmv'
		, 'wmx'=>'video/x-ms-wmx'
		, 'wmz'=>'application/x-ms-wmz'
		, 'wp6'=>'application/x-wp6'
		, 'wpd'=>'application/x-wpd'
		, 'wpg'=>'application/x-wpg'
		, 'wpl'=>'application/vnd.ms-wpl'
		, 'wq1'=>'application/x-wq1'
		, 'wr1'=>'application/x-wr1'
		, 'wri'=>'application/x-wri'
		, 'wrk'=>'application/x-wrk'
		, 'ws'=>'application/x-ws'
		, 'ws2'=>'application/x-ws'
		, 'wsc'=>'text/scriptlet'
		, 'wsdl'=>'text/xml'
		, 'wvx'=>'video/x-ms-wvx'
		, 'xdp'=>'application/vnd.adobe.xdp'
		, 'xdr'=>'text/xml'
		, 'xfd'=>'application/vnd.adobe.xfd'
		, 'xfdf'=>'application/vnd.adobe.xfdf'
		, 'xhtml'=>'text/html'
		, 'xls'=>'application/vnd.ms-excel'
		, 'xls'=>'application/x-xls'
		, 'xlw'=>'application/x-xlw'
		, 'xml'=>'text/xml'
		, 'xpl'=>'audio/scpls'
		, 'xq'=>'text/xml'
		, 'xql'=>'text/xml'
		, 'xquery'=>'text/xml'
		, 'xsd'=>'text/xml'
		, 'xsl'=>'text/xml'
		, 'xslt'=>'text/xml'
		, 'xwd'=>'application/x-xwd'
		, 'x_b'=>'application/x-x_b'
		, 'x_t'=>'application/x-x_t' 
	) ;
}
?>